#ifndef MUTEX_H
#define MUTEX_H

//the maximum number of mutexes available
#define MAX_MUTEX_NUM_BITS	10
#define MAX_MUTEX_NUM		(1<<MAX_MUTEX_NUM_BITS)

typedef int uthread_t;

typedef struct
{
	int lock;	//- means the lock is free, and 1 means the lock is set
} uthread_spinlock_t;

#define UTHREAD_SPINLOCK_INITIALIZER		{.lock = 0			}

extern int uthread_spin_lock(uthread_spinlock_t *t);
extern int uthread_spin_unlock(uthread_spinlock_t *t);
extern int uthread_spin_trylock(uthread_spinlock_t *t);

typedef struct
{
	int lock;		//0 means the lock is free, and 1 means the lock is set
	uthread_t  owner;	//the owner of this mutex
	hlist_head	 mutex_hlist_head;
} uthread_mutex_t;

#define UTHREAD_MUTEX_INITIALIZER		{.lock = 0,  			\
						 .owner = -1, 			\
						 .mutex_hlist_head = HLIST_HEAD_INIT}

extern int uthread_mutex_lock(uthread_mutex_t *t);
extern int uthread_mutex_unlock(uthread_mutex_t *t);
extern int uthread_mutex_trylock(uthread_mutex_t *t);

typedef struct
{
	uthread_mutex_t	* mutex;		//the mutex related to this condition var
	hlist_head	cond_hlist_head;	//list of uthreads waiting for this cond
} uthread_cond_t;

#define UTHREAD_COND_INITIALIZER		{.mutex = NULL,			\
						 .cond_hlist_head = HLIST_HEAD_INIT}

extern int uthread_cond_wait(uthread_cond_t *cond, uthread_mutex_t *mutex);
extern int uthread_cond_signal(uthread_cond_t *cond);
extern int uthread_cond_broadcast(uthread_cond_t *cond);

#endif
